package abel.wlmr.model.type;

import abel.util.StdBcdNumber;
import abel.wlmr.model.WlmrException;
import io.netty.buffer.ByteBuf;

/**
 * B.5.12.2.5.9 ERC21：终端故障记录
 * 事件记录的数据格式见表 B.193。
 * 表B.193 终端故障记录数据单元格式
 * 数据内容 数据格式 字节数
 * ERC=21 BIN 1
 * 长度 Le BIN 1
 * 发生时间：分时日月年 见附录 C.15 5
 * 终端故障编码 BIN 1
 * ——终端故障编码定义见表 B.194。
 * 表B.194
 * 终端故障编码 故障
 * 1 终端主板内存故障
 * 2 时钟故障
 * 3 主板通信故障
 * 4 485 抄表故障
 * 5 显示板故障
 * 6 载波通道异常
 * 7 M_BUS 通信故障
 * 8 无线通讯故障
 * 8-255 备用
 * 
 * @author Abel
 *
 */
public class Erc21Body extends ErcBaseBody {

    private static final short FIXED_LENGTH = 5 + 1;

    /**
     * 发生时间：分时日月年 见附录 C.15 5
     */
    private StdBcdNumber openTime;

    private TermErrorType failureNo;

    public Erc21Body(short guessedLen) {
        super(guessedLen, (short) 21, FIXED_LENGTH);
    }

    public Erc21Body() {
        this((short) -1);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.ErcBaseBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (openTime == null || openTime.length() != 5) {
            throw new IllegalArgumentException("occur time should be C.15 format");
        }

        if (failureNo == null) {
            throw new IllegalArgumentException("failure no can't be null");
        }

        // append erc & le.
        buf.writeByte(erc);
        buf.writeByte(le);

        buf.writeBytes(openTime.toBytes());
        buf.writeByte(failureNo.getValue());

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.ErcBaseBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        buf.skipBytes(MIN_LENGTH);

        openTime = new StdBcdNumber();
        openTime.populateBytes(buf, 5);

        failureNo = TermErrorType.findEnumByValue(buf.readByte() & 0xFF);

        return MIN_LENGTH + FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        return MIN_LENGTH + FIXED_LENGTH;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{openTime:%s, failureNo:%s}", openTime, failureNo);
    }

    /**
     * 发生时间：分时日月年 见附录 C.15 5
     * 
     * @return the openTime
     */
    public StdBcdNumber getOpenTime() {
        return openTime;
    }

    /**
     * 发生时间：分时日月年 见附录 C.15 5
     * 
     * @param openTime
     *            the openTime to set
     */
    public void setOpenTime(StdBcdNumber openTime) {
        if (openTime == null || openTime.length() != 5) {
            throw new IllegalArgumentException("occur time should be C.15 format");
        }

        // may throw IAE
        openTime.toMeterC15Joda();

        this.openTime = openTime;
    }

    /**
     * @return the failureNo
     */
    public TermErrorType getFailureNo() {
        return failureNo;
    }

    /**
     * @param failureNo
     *            the failureNo to set
     */
    public void setFailureNo(TermErrorType failureNo) {
        if (failureNo == null) {
            throw new IllegalArgumentException("failure no can't be null");
        }

        this.failureNo = failureNo;
    }
}
